/* Copyright (c) 2003 The Nutch Organization. All rights reserved. */ /* Use subject to the conditions in http://www.nutch.org/LICENSE.txt. */ package net.nutch.util; import java.util.*; import java.util.logging.*; import net.nutch.util.LogFormatter; /************************************************ * ThreadPool.java * * ThreadPool maintains a large set of threads, which * can be dedicated to a certain task, and then recycled. ***********************************************/ public class ThreadPool { /** * A TaskThread sits in a loop, asking the pool * for a job, and servicing it. That's all it does. */ class TaskThread extends Thread { /** * Get a job from the pool, run it, repeat. * If the job is null, we exit the loop. */ public void run() { while (true) { Runnable r = obtainJob(); if (r == null) { break; } try { r.run(); } catch (Exception e) { System.err.println("E: " + e); e.printStackTrace(); } } } } int numThreads; boolean running = false; Vector jobs; /** * Creates a pool of numThreads size. * These threads sit around waiting for jobs to * be posted to the list. */ public ThreadPool(int numThreads) { this.numThreads = numThreads; jobs = new Vector(37); running = true; for (int i = 0; i < numThreads; i++) { TaskThread t = new TaskThread(); t.start(); } Logger l = LogFormatter.getLogger("net.nutch.util"); l.fine("ThreadPool created with " + numThreads + " threads."); } /** * Gets a job from the queue, returns to worker thread. * When the pool is closed down, return null for all * obtainJob() requests. That tells the thread to * shut down. */ Runnable obtainJob() { Runnable job = null; synchronized (jobs) { while (job == null && running) { try { if (jobs.size() == 0) { jobs.wait(); } } catch (InterruptedException ie) { } if (jobs.size() > 0) { job = (Runnable) jobs.firstElement(); jobs.removeElementAt(0); } } } if (running) { // Got a job from the queue return job; } else { // Shut down the pool return null; } } /** * Post a Runnable to the queue. This will be * picked up by an active thread. */ public void addJob(Runnable runnable) { synchronized (jobs) { jobs.add(runnable); jobs.notifyAll(); } } /** * Turn off the pool. Every thread, when finished with * its current work, will realize that the pool is no * longer running, and will exit. */ public void shutdown() { running = false; Logger l = LogFormatter.getLogger("net.nutch.util"); l.fine("ThreadPool shutting down."); } }